/*
 * EventDispatcher.h
 *
 *  Created on: 24 nov 2011
 *      Author: Robert
 *
 * This class and related classes are mirroring Flash's EventDispatcher, and partly inspired
 * by LiraNuna's http://www.liranuna.com/implementing-eventdispatcher-in-cpp/
 * Main difference is with the actual call back, which is implemented by a functor instead of
 * a function pointer, to allow it to be fully OO.
 *
 * Idea is to use this as a base class for classes that need to handle events. See Flash or
 * JavaScript documentation for learning the concept.
 *
 * It is not fully implemented with canceling and bubbles and so forth.
 *
 * Usage:
 *   button.addEventListener(Button::EVENT_CLICK, EventListenerT<Window>(window, &Window::onButtonClick));
 *
 * Problems:
 *   Ownership of the listener functor. The dispatcher stores a reference to the original, so the caller
 *   needs to keep it alive and free it when appropriate. Dispatcher should probably make a copy instead
 *   which would require copy and comparison logic on part of the EventListener. Or accept a shared_ptr.
 *
 *   There should also be a version of the listener that can take a plain function pointer.
 *
 *   Out of laziness, EventType is a string, which is very inefficient. It should be changed to something
 *   different, like enum or maybe pointers to static strings or something. In the meantime, avoid
 *   using string literals in the code, then it will be easier to change later. Eg:
 *
 *   	class Button {
 *   		static const EventType EVENT_CLICK;
 *   	}
 *   	const EventType Button::EVENT_CLICK = "EVENT_CLICK";
 */

#ifndef EVENTDISPATCHER_H_
#define EVENTDISPATCHER_H_

#include "Event.h"
#include "EventListener.h"
#include <map>

class EventDispatcher
{
	public:

		// Note the listener is NOT owned by the dispatcher, so it must be deleted by the user
		void addEventListener(const EventType &type, const EventListener &listener, bool useCapture = false, int priority = 0, bool useWeakReference = false);
		void dispatchEvent(const Event &event);
		bool hasEventListener(const EventType &type) const;
		void removeEventListener(const EventType &type, const EventListener &listener, bool useCapture = false);
		//bool willTrigger(const EventType &type);

	private:
		/**
		 * EVENT_TYPE => (
		 *    (priority, listener),
		 *    ...
		 * )
		 */
		std::map<const EventType, std::multimap<int, const EventListener &> > eventListeners;

};


#endif /* EVENTDISPATCHER_H_ */
